<template>
  <div class="ai-chat">
    <el-popover
      v-model:visible="chatVisible"
      placement="bottom-end"
      :width="500"
      trigger="click"
    >
      <template #reference>
        <el-button type="primary" :icon="ChatRound" circle />
      </template>
      
      <div class="chat-container">
        <div class="chat-messages" ref="messagesRef">
          <div v-for="(msg, index) in messages" :key="index" 
               :class="['message', msg.role]">
            <div class="message-content" 
                 :class="{ 'markdown-body': msg.role === 'assistant' }"
                 v-if="msg.role === 'user'">
              {{ msg.content }}
            </div>
            <div class="message-content markdown-body" 
                 v-else
                 v-html="renderMarkdown(msg.content)">
            </div>
          </div>
        </div>
        
        <div class="chat-input">
          <el-input
            v-model="inputMessage"
            placeholder="输入消息..."
            :disabled="loading"
            @keyup.enter="sendMessage"
          >
            <template #append>
              <el-button
                type="primary"
                :loading="loading"
                @click="sendMessage"
              >
                发送
              </el-button>
            </template>
          </el-input>
        </div>
      </div>
    </el-popover>
  </div>
</template>

<script setup>
import { ref, nextTick, onMounted } from 'vue'
import { ChatRound } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import MarkdownIt from 'markdown-it'
import hljs from 'highlight.js'

const md = new MarkdownIt({
  html: true,
  linkify: true,
  typographer: true,
  highlight: function (str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return hljs.highlight(str, { language: lang }).value
      } catch (__) {}
    }
    return hljs.highlightAuto(str).value
  }
})

const chatVisible = ref(false)
const inputMessage = ref('')
const loading = ref(false)
const messages = ref([
  { role: 'assistant', content: '你好！我是 AI 助手，有什么可以帮你的吗？' }
])
const messagesRef = ref(null)

const renderMarkdown = (content) => {
  return md.render(content)
}

const scrollToBottom = async () => {
  await nextTick()
  const container = messagesRef.value
  if (container) {
    container.scrollTop = container.scrollHeight
  }
}

const sendMessage = async () => {
  if (!inputMessage.value.trim() || loading.value) return
  
  const userMessage = inputMessage.value
  messages.value.push({ role: 'user', content: userMessage })
  inputMessage.value = ''
  loading.value = true
  
  // 先添加一个空的助手消息，用于后续流式更新
  const assistantMessageIndex = messages.value.length
  messages.value.push({ role: 'assistant', content: '' })
  await scrollToBottom()
  
  try {
    const response = await fetch('http://localhost:8080/api/chat', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Accept': 'text/event-stream'
      },
      body: JSON.stringify({ message: userMessage })
    })
    
    if (!response.ok) {
      throw new Error('请求失败')
    }
    
    const reader = response.body.getReader()
    const decoder = new TextDecoder()
    
    // 流式处理响应
    while (true) {
      const { done, value } = await reader.read()
      if (done) break
      
      const chunk = decoder.decode(value, { stream: true })
      // 将新收到的内容附加到现有消息上
      messages.value[assistantMessageIndex].content += chunk
      await scrollToBottom()
    }
  } catch (error) {
    console.error('发送消息失败:', error)
    ElMessage.error('发送消息失败')
    // 如果失败，更新错误信息
    if (messages.value[assistantMessageIndex]) {
      messages.value[assistantMessageIndex].content = '消息发送失败，请重试。'
    }
  } finally {
    loading.value = false
    scrollToBottom()
  }
}

onMounted(() => {
  scrollToBottom()
})
</script>

<style>
@import 'highlight.js/styles/github.css';
@import 'github-markdown-css';
</style>

<style scoped>
.ai-chat {
  position: fixed;
  top: 20px;
  right: 20px;
  z-index: 1000;
}

.chat-container {
  display: flex;
  flex-direction: column;
  height: 500px;
}

.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  margin-bottom: 10px;
}

.message {
  margin-bottom: 10px;
  display: flex;
}

.message.user {
  justify-content: flex-end;
}

.message-content {
  max-width: 80%;
  padding: 8px 12px;
  border-radius: 8px;
  background-color: #f4f4f5;
  word-break: break-word;
  color: #333;
}

.message.user .message-content {
  background-color: #409eff;
  color: white;
}

.markdown-body {
  background-color: #f8f9fa;
  padding: 16px;
  border-radius: 8px;
  font-size: 14px;
  line-height: 1.6;
  color: #333;
}

.markdown-body pre {
  background-color: #f3f4f5;
  padding: 12px;
  border-radius: 4px;
  margin: 8px 0;
}

.markdown-body code {
  font-family: Consolas, Monaco, 'Andale Mono', monospace;
  background-color: rgba(0, 0, 0, 0.05);
  padding: 2px 4px;
  border-radius: 3px;
}

.message.user .markdown-body {
  color: inherit;
  background-color: transparent;
}

.chat-input {
  padding: 10px;
  border-top: 1px solid #dcdfe6;
}
</style> 